
// my custom defines
//#include <stddef.h>
#include "stm32f10x.h"
#include "main.h"


// TODO defines init for buttons ?  

// packet buffer, incoming and outgoing
//u8 g_PktRXBuff[pktBuffSize];
u8 g_PktTXBuff[pktBuffSize];
extern CircularBuffer rxUSCBuff;
u8 g_Vars[g_VarsSize];
//u8 newg_Vars[g_VarsSize];
pgloabalVars newgVars;


//struct glbVars *newgVars;
//struct glbVars newgVarsst;
struct glbVars *mygVars;
//struct glbVars mygVarsst;
volatile unsigned int stam;

// main related vars
u32 pktTimeoutAt = 0x00;
u32 idleTimeoutAt = 0x00;
u8 sleeping;

int main(void)
{
	u8 nothing =0;
	pktErr packetErr;
	u16 bytesAvail = 0;
	u16 respSize = 0;
	sleeping = false;
	//newgVars = (void*)&newg_Vars;	// new stuff from client
	mygVars = (void*)&g_Vars; // this is what gets sent to client

	// init all systems
	startupSystems();

	mygVars->dataState= 1; // start in idle state

	while(1)
	{
		

		// while(AIRSER_H())
		//if( USRBTN_H() )

		// Switch on the state of the robot
		switch(mygVars->dataState)
		{
			case idle: // 

				// restart int in case we overflowed our buffer
				USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

				// sleep and wake on RX of uart ? 
				mygVars->dataState = waitingfordata;

				// start idle timeout, if we stay in idle too long 
				// disable everything 
				if(idleTimeoutAt == 0)
				{
					idleTimeoutAt = (getSecondTick() + 1);
				} 

				break;

			case waitingfordata: 
				// bytes available in circular buffer
				bytesAvail = cbCount(&rxUSCBuff);

				if(bytesAvail == 0)
				{
					// if we have timed out shut down, low power
					if(sleeping == false && getSecondTick() > idleTimeoutAt)
					{
						idleTimeoutAt = 0;
						newgVars->enabled = 0; // turn everything off!
						sleeping = true;
						doTasks();	  // make it so
					}
				}

				// waiting for more data from a packet, should we timeout ? 
				if(packetErr.ERR == 1 && getSecondTick() > pktTimeoutAt)
				{
					pktTimeoutAt = 0;
					packetErr.ERR = 0;
					packetErr.SIZE = 0;
					// flush the rest of the buffer
					while(!cbIsEmpty(&rxUSCBuff))
					{
						cbRead(&rxUSCBuff, &nothing);
					}
					printf("%lu : Timeout", getSecondTick());
					mygVars->dataState = idle;
					break;
				}

				// if we have enough to make a packet and we are not waiting for more from a packet
				if(bytesAvail >= (hdrSize + crcSize + 4) || ( packetErr.ERR == 1 && bytesAvail >= packetErr.SIZE ) )
				{
					printf("got data, checking");
					checkPacket(&rxUSCBuff, &packetErr);

					switch(packetErr.ERR)
					{
						case 0: // no error, valid packet
							mygVars->dataState = gotnewdata;
							pktTimeoutAt = 0;
							break;

						case 1: // we need more data 
							if(pktTimeoutAt == 0)
							{
								pktTimeoutAt = (getSecondTick() + 1);
							} 
							break;

						case 2: // crc error or invalid packet
							printf("%lu : CRC Err ", getSecondTick());
							mygVars->dataState = idle;
							break;
						
						case 3: // timeout waiting for write data
							printf("%lu : Timeout ", getSecondTick());
							mygVars->dataState = idle;
							break;

						case 4:
							printf("%lu : Invalid header ", getSecondTick());
							mygVars->dataState = idle;
							break;

						case 0xFF: // no valid data in packet !
							printf("%lu : No valid data in packet", getSecondTick());
							//cbInit(&rxUSCBuff); // reset circular buffer
							mygVars->dataState = idle;
							break;

						default:
							printf("%lu : Unknown data state", getSecondTick());
							mygVars->dataState = idle;
							break;

					}
					//RxCounter = 0;
					//dataState = gotnewdata;
				}

				// otherwise do something else here
				break;
			
			case gotnewdata:
				// Process the packet, all of the needed vars
				// were saved when we checked the packet
				respSize = processPacket();

				// reset our idle timeout, we are NOT idle !
				idleTimeoutAt = 0;
				// if we were asleep wake up ! 
				if(sleeping == true)
				{
					// we let the user turn stuff on, we automatically turn it off
					//newgVars->enabled = 0xFF; 	// turn everything on
					sleeping = false;
				}

				// do everything that should be done
				doTasks();	  				// make it so

				// if we get a size back there is data ready to be
				// sent out, else there is nothing to respond 
				if(respSize)
				{
					mygVars->dataState = readytosenddata;
				}else{ 

					// if we dont get a response size we must have
					// gotten a write message, this is when we update
					// all of the items
					mygVars->dataState = idle;
				}
				break;

			case readytosenddata:
				// send out the data, todo get right size!
				DMA_TXPush();
				mygVars->dataState = idle;
				break;

			case sendingdata:
				// more free time here
				break;

			case dataerror:
				// there is an error, just start over
				printf("Error Uart Flags: 0x%X", USART2->SR);
				mygVars->dataState = idle;
				break;

			default:
				printf("PacketState: %d\n\r", mygVars->dataState);
				break;
				//Delay(100);
		}
		//sleep wake on data rx if no packets in several seconds
		//Delay(100);
		//printf("working");
	}
}

/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the USART */
  //USART_SendData(USART3, (uint8_t) ch);

  /* Loop until the end of transmission */
  //while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
  //{}

  return ch;
}

// terminal ! 
//	while(1)
//	{
//		i=0;
//		do
//		{ 
//		  if((USART_GetFlagStatus(USART2, USART_FLAG_RXNE) != RESET)&&(i < pktBuffSize))
//		  {
//		     g_PktBuff[i] = USART_ReceiveData(USART2);
//		     USART_SendData(USART2, g_PktBuff[i++]);
//		  }   
//		}while((g_PktBuff[i - 1] != '\r')&&(i != pktBuffSize));
//		for(i=0; i<pktBuffSize; i++)
//		{
//			g_PktBuff[0] = i;
//		}
//	}
